\documentclass{document}

\begin{document}

\frontpage{1.0}

\tableofcontents

\newpage

%\pagestyle{fancy}

\section{\texttt{TRUE} und \texttt{FALSE} (10\%)}

Um die beiden Konstanten \texttt{TRUE} und \texttt{FALSE} zu implementieren,
musste man lediglich die beiden Symbole in der lexikalischen Analyse
erkennen:
\begin{lstlisting}
	keywords.put("TRUE", Symbol.Id.TRUE);
	keywords.put("FALSE", Symbol.Id.FALSE);
\end{lstlisting}
Anschließend müssen die neu erkannten Symbole auch in der syntaktischen Analyse
korrekt behandelt werden. Da es sich hier um Literale handelt, liegt es nahe
dies in der bereits vorhandenen Methode \texttt{literal} zu tun:
\begin{lstlisting}
	case TRUE:
		e = new LiteralExpression(1, ClassDeclaration.boolType, new Position(symbol.line, symbol.column));
		nextSymbol();
		break;
	case FALSE:
		e = new LiteralExpression(0, ClassDeclaration.boolType, new Position(symbol.line, symbol.column));
		nextSymbol();
		break;
\end{lstlisting}
Wie unschwer zu erkennen ist, sind \texttt{TRUE} und \texttt{FALSE} Literale vom
Typ \texttt{boolType} mit jeweils den Werten \texttt{1} beziehungsweise
\texttt{0}.


\section{\texttt{ELSE} und \texttt{ELSEIF} (10\%)}

Analog zur vorhergegangenen Aufgabe muss die lexikalische Analyse um die
entsprechenden Schlüsselworte erweitert werden.\par

Damit die Syntaxanalyse die \texttt{ELSE}- beziehungsweise
\texttt{ELSEIF}-Anweisungen korrekt verschachtelt werden, wird, solange es ein
\texttt{ELSEIF} gibt, eine neue Anweisung erstellt, die dem vorherigen
\texttt{IF} bezeihungsweise \texttt{ELSEIF} angehangen wird.
\begin{lstlisting}
	while (symbol.id == Symbol.Id.ELSEIF)
	{
		nextSymbol();
		ElseIfStatement se = new ElseIfStatement(oexpression());
		s.elseIfStatement = se;
		s = se;
		expectSymbol(Symbol.Id.THEN);
		if (symbol.id != Symbol.Id.ELSE && symbol.id != Symbol.Id.ELSEIF)
		{
			while (symbol.id != Symbol.Id.END && symbol.id != Symbol.Id.ELSEIF
					&& symbol.id != Symbol.Id.ELSE)
				statement(s.thenStatements);
		}
	}
\end{lstlisting}

Um ein \texttt{ELSE} in einer \texttt{IF}-Anweisung zu ermöglichen, muss
man in der Code-Generierung von \texttt{IF} ein weiteres \texttt{Code-Label} generieren
und hinter dem \texttt{THEN}-Code einfügen. Nun kann man, falls ein
\texttt{ELSE}-Teil vorhanden ist, dorthin springen.
\begin{lstlisting}
	if (hasElse())
		code.println("JPC R5, " + elseLabel + " ; Sprung zu ELSE");
\end{lstlisting}
Weiterhin muss man darauf achten, dass nach dem \texttt{THEN}-Teil direkt zum
Ende der \texttt{IF}-Anweisung gesprungen wird, da sonst der \texttt{ELSE}-Teil
zusätzlich ausgeführt werden würde.\par
\texttt{ELSEIF} ist in unserer Implementierung einfach eine Unterklasse der
\texttt{IF}-Anweisung, die bis auf die Kommentar-Ausgabe vollkommen identisch
ist. In der \texttt{IF}-Anweisung wird dann noch überprüft, ob ein
\texttt{ELSEIF} vorhanden ist. Wenn das zutrifft, wird der entsprechende Code an
der Position des \texttt{ELSE} generiert.
\begin{lstlisting}
	if (elseIfStatement != null)
	{
		code.println(elseLabel + ":");
		elseIfStatement.generateCode(code, endLabel);
	}
\end{lstlisting}


\section{Boolsche Arithmetik (\texttt{AND}, \texttt{OR}, \text{NOT}) (10\%)}

Analog zur vorhergegangenen Aufgabe muss die lexikalische Analyse um die
entsprechenden Schlüsselworte erweitert werden.\par

In der Syntaxanalyse muss dann eingebaut werden, dass die Produktionen korrekt
interpretiert werden. Dazu haben wir den Syntaxbaum erweitert (und
entsprechende Methoden implementiert).
\begin{lstlisting}
	oexpression  ::= aexpression { 'OR' aexpression | 'OR ELSE' aexpression }  
	aexpression  ::= relation { 'AND' relation | 'AND THEN' relation }
	...
	factor       ::= ( '-' | 'NOT' ) factor
	               | memberaccess
\end{lstlisting}
Im \texttt{statement}-Knoten des Baumes haben wir die alten \texttt{relation}
und \texttt{expression} mit \texttt{oexpression} substituiert.

Anschließend mussten noch \texttt{BinaryExpression} und \texttt{UnaryExpression}
an die neuen Operatoren angepasst werden.


\section{Vordefinierte Klasse \texttt{Boolean} (10\%)}

Um die vordefinierte Klasse \texttt{Boolean} zu implementieren, musste die
Klasse erstellt werden und im Programm registriert werden\footnote{Hier haben
wir bereits den vereinfachten Code für mehrere eigene Klassen}.
\begin{lstlisting}
	static final ClassDeclaration boolClass	= new ClassDeclaration(new Identifier("Boolean", null));
	...
	this.theClasses.add(ClassDeclaration.boolClass);
\end{lstlisting}

Anschließend musste noch ein Unboxing beziehungsweise Boxing für diese Klasse
in den Basistyp beziehungsweise von dem Basistyp in die Klasse implementiert
werden. Dies erfolgt analog zur bereits implementierten Routine für die Klasse
\texttt{Integer}.


\section{Mehrere eigene Klassen (10\%)}

Um mehrere eigene Klassen zu Unterstützen, musste man im Programm die Limitation
auf eine Klasse (\texttt{theClass}) auf mehrere Klassen erweitern
(Liste \texttt{theClasses}). Hier werden alle Klassen eingetragen, die im
Programm definiert werden. Dazu muss man in der Syntaxanalyse mehrere Klassen
zulassen:
\begin{lstlisting}
	while (symbol.id == Symbol.Id.CLASS)
		classdecls.add(classdecl());
\end{lstlisting}

Sowohl \texttt{Integer} als auch \texttt{Boolean} haben wir ebenfalls in diese
Liste eingetragen.

Der etwas komplexere Teil dieser Aufgabe lag darin, dass vor der Kontextanalyse
der Methodenrümpfe einer jeden Klasse alle Methoden und Attribute von jeder
Klasse bekannt sein müssen. Dafür haben wir die Kontextanalyse der
\texttt{ClassDeclaration} angepasst. Mittels eines Parameters wird betimmt, ob
zuerst nur die Kontextanalyse der Klasse ansich stattfinden soll oder die der
Methoden.
\begin{lstlisting}
	void contextAnalysis(Declarations declarations, boolean firstPass) ...
\end{lstlisting}

\section{Methoden können Parameter haben (10\%)}

Zunächst haben wir die Grammatik bei \texttt{memberdecl} und \texttt{varorcall}
erweitert. Dazu haben wir in der Methode \texttt{memberdecl} folgenden Code
hinzugefügt:

\begin{lstlisting}
	MethodDeclaration m = new MethodDeclaration(expectIdent());
	if (symbol.id == Symbol.Id.LPAREN)
	{
		nextSymbol();
		vardecl(m.params, false, true);
		while (symbol.id == Symbol.Id.SEMICOLON)
		{
			nextSymbol();
			vardecl(m.params, false, true);
		}
		expectSymbol(Symbol.Id.RPAREN);
	}
\end{lstlisting}

Für die Erweiterung zu \texttt{memberdecl} haben wir die Methode
\texttt{varorcall} hinzugefügt und diese wird dann in \texttt{memberaccess}
und \texttt{literal} aufgerufen.

Anschließend haben wir bei \texttt{MethodDeclaration} das Attribut
\begin{lstlisting}
	LinkedList<VarDeclaration>	params		= new LinkedList<VarDeclaration>();
\end{lstlisting}
und bei \texttt{VarOrCall} das Attribut
\begin{lstlisting}
	LinkedList<Expression>	params	= new LinkedList<Expression>();
\end{lstlisting}
hinzugefügt. \par

In der Kontextanalyse haben wir für den Typvergleich der Parameter die Methode
\texttt{contextAnalysisForMember} in \texttt{VarOrCall} um folgenden Code
ergänzt:
\begin{lstlisting}
	MethodDeclaration m = (MethodDeclaration) identifier.declaration;
	if (params.size() != m.params.size())
		throw new CompileException("Parameter-Anzahl stimmt nicht mit deklarierter
		Anzahl ueberein", position);
	int i = 0;
	for (Expression e : params)
	{
		e.contextAnalysis(baseDeclarations);
		e = e.box(baseDeclarations);
		params.set(i, e);
		VarDeclaration v = m.params.get(i++);
		baseDeclarations.resolveType(v.type);
		if (!((ClassDeclaration) v.type.declaration).isA(e.type))
			throw new CompileException(''Parameter-Typ stimmt nicht mit deklariertem Typ
			ueberein'', e.position);
		
	}
\end{lstlisting}

Den Stapelrahmen für die Parameter haben wir in \texttt{contextAnalysis} von
\texttt{MethodDeclaration} angepasst.
\begin{lstlisting}
	self.offset = -2 - params.size();
	base.offset = -2 - params.size();
	int offset = self.offset + 1;

	for (VarDeclaration p : params)
	{
		declarations.add(p);
		p.offset = offset++;
	}
	
	offset += 2;
	
	for (VarDeclaration v : vars)
	{
		declarations.add(v);
		v.offset = offset++;
	}
\end{lstlisting}

Bei der Synthese werden die Parameter in \texttt{VarOrCall} auf den Stapel
gepackt 
\begin{lstlisting}
	for (Expression e : params)
	{
		e.generateCode(code);
	}
\end{lstlisting}
und entfernt werden diese wieder in \texttt{MethodDeclaration} durch das
hinzufügen von \texttt{params.size()}.
\begin{lstlisting}
	code.println("MRI R5, " + (vars.size() + params.size() + 3));
\end{lstlisting}


\section{Methoden können Ergebnisse haben (\texttt{RETURN}) (10\%)}

Analog zu vorhergegangenen Aufgaben muss die lexikalische Analyse um das
entsprechende Schlüsselwort erweitert werden. \par

Danach haben wir in der Syntaxanalyse die Grammatik bei \texttt{memberdecl} und
\texttt{statement} erweitert. Hierbei haben wir in \texttt{memberdecl} den Code 
mit
\begin{lstlisting}
	if (symbol.id == Symbol.Id.COLON)
	{
		nextSymbol();
		m.type = expectResolvableIdent();
	} 
\end{lstlisting}
und in \texttt{statement} mit
\begin{lstlisting} 
	case RETURN:
		nextSymbol();
		ReturnStatement r = new ReturnStatement();
		statements.add(r);
		if (symbol.id == Symbol.Id.SEMICOLON)
			nextSymbol();
		else
		{
			r.expression = oexpression();
			expectSymbol(Symbol.Id.SEMICOLON);
		}
		break;
\end{lstlisting}
ergänzt.

Anschließend haben wir die Klasse \texttt{ReturnStatement} für die
\texttt{RETUREN}-Anweisungen erstellt und in \texttt{MethodDeclaration} das
Attribut
\begin{lstlisting} 
	ResolvableIdentifier		type;
\end{lstlisting}
hinzugefügt, um den Rückgabetyp von Methoden zu Speichern und auflösen zu
können.\par

Während der Kontextanalyse wird in \texttt{MethodDeclaration} überprüft, ob die
Methode auf allen Pfaden eine \texttt{RETURN}-Anweisung besitzt. Dafür haben wir
unteranderem die \texttt{Statement}-Klasse um die Methode \texttt{returns}
erweitert. Standartmäßig führt nur die \texttt{RETURN}-Anweisung selbst zur
Rückgabe. Die Ausnahme ist die \texttt{IF}-Anweisung, die zur Rückgabe kommt,
wenn sowohl der \texttt{THEN}-Pfad als auch der \texttt{ELSE}-Pfad zur Rückgabe
führen.
\begin{lstlisting}
	boolean hasReturn = false;
	for (Statement s : statements)
	{
		s.contextAnalysis(declarations);
		hasReturn = hasReturn || s.returns();
	}
	if (!hasReturn)
		if (type == null)
		{
			Statement s = new ReturnStatement();
			statements.add(s);
			s.contextAnalysis(declarations);
		}
		else
		{
			throw new CompileException("Diese Methode erwartet eine Rueckgabe des Typs "
			+ type.declaration, identifier.position);
		}
	else
		if (identifier.name.equals("main"))
			if (type != null)
				throw new CompileException("Main darf keinen Rueckgabetyp haben",
				identifier.position);
			
\end{lstlisting}
\begin{lstlisting}
	boolean returns()
	{
		boolean returns = false;
		for (Statement s : thenStatements)
			if (s.returns())
				returns = true;
		if (!returns)
			return false;
		if (elseIfStatement != null)
			returns = elseIfStatement.returns();
		if (!returns)
			return false;
		returns = false;
		for (Statement s : elseStatements)
			if (s.returns())
				return true;
		return false;
	}
\end{lstlisting}
Hat die Methode nicht auf allen Pfaden ein \texttt{RETURN}, so wird bei
\texttt{Void}-Methoden einfach ein \texttt{RETURN} am Ende eingefügt. Ansonsten
Fehler.

In der \texttt{RETURN}-Anweisung selbst wird während der Kontextanalyse der
Rückgabetyp mit dem erwarteten Typ verglichen.
\begin{lstlisting}
	if (expression != null)
	{
		if (declarations.currentMethod.type == null)
			throw new CompileException("Es wird kein Rueckgabe-Typ erwartet", null);
		expression = expression.contextAnalysis(declarations);
		expression = expression.box(declarations);
		expression.type.check((ClassDeclaration) declarations.currentMethod.type.declaration, expression.position);
	}
	else
		if (declarations.currentMethod.type != null)
		{
			throw new CompileException("Es wird ein Rueckgabe-Typ erwartet", null);
		}
\end{lstlisting}

Um den Rückgabetyp in \texttt{VarOrCall} zu übernehmen, haben wir den Code wie
folgt angepasst:
\begin{lstlisting}
	if (m.type == null)
		type = ClassDeclaration.voidType;
	else
		type = (ClassDeclaration) m.type.declaration; 
\end{lstlisting}

Da jede Methode garantiert ein \texttt{RETURN} auf möglichen Pfaden besitzt,
wird das Methoden-Ende ab jetzt von der \texttt{RETURN}-Anweisung generiert. Sie
ruft folgende Methode in \texttt{MethodDeclaration} auf:
\begin{lstlisting}
	void generateExitCode(CodeStream code, Expression e)
	{
		code.println("; END METHOD " + identifier.name);
		if (e != null)
		{
			code.println("; RETURN");
			e.generateCode(code);
			code.println("MRM R7, (R2) ; Ergebnis zwischenspeichern");
		}
		code.println("MRI R5, " + (vars.size() + params.size() + 3));
		code.println("SUB R2, R5 ; Stack korrigieren");
		if (e != null)
			code.println("MMR (R2), R7 ; RETURN auf den Stack");
		code.println("SUB R3, R1");
		code.println("MRM R5, (R3) ; Ruecksprungadresse holen");
		code.println("ADD R3, R1");
		code.println("MRM R3, (R3) ; Alten Stapelrahmen holen");
		code.println("MRR R0, R5 ; Ruecksprung");
	}
\end{lstlisting}


\section{Vererbung (dynamische Bindung von Methoden, \texttt{BASE}) (10\%)}

- nicht vollständig implementiert -

\section{Speicherbereinigung, Variablen und Attribute werden automatisch
initialisiert (20\%)}

- nicht implementiert -

\section{Bonusaufgaben}

\subsection{Erweiterung um AND THEN und OR ELSE (5\%)}

Analog zu vorhergegangenen Aufgaben muss die lexikalische Analyse um die
entsprechenden Schlüsselworte erweitert werden.\par

In der Syntaxanalyse wird, wenn ein \texttt{AND} oder ein \texttt{OR} gefunden
wird, anschließend nach einem \texttt{THEN} bzw. \texttt{ELSE} geschaut und wenn
eines dieser beiden Token gefunden wird, wird \texttt{operator} dementsprechend
verändert.
\begin{lstlisting}
	if (symbol.id == Symbol.Id.THEN)
	{
		operator = Symbol.Id.ANDTHEN;
		nextSymbol();
	}
\end{lstlisting}
und
\begin{lstlisting}
	if (symbol.id == Symbol.Id.ELSE)
	{
		operator = Symbol.Id.ORELSE;
		nextSymbol();
	}
\end{lstlisting}

In der Synthese haben wir in \texttt{BinaryExpression} die Methode
\texttt{generateCode} um einen weiteren Parameter (endLabel) erweitert. Dieser
dient dazu um an das Ende der äußersten \texttt{BinaryExpression} zu
spingen.\par

Im folgenden Code sehen wir, dass wenn es sich bei unserer
\texttt{BinaryExpression} um einen \texttt{AND THEN} oder einen \texttt{OR ELSE}
handelt. In diesem Fall fügen wir eine Prüfung ein, ob der
\texttt{leftOperand} bereits dafür sorgt, sodass der \texttt{rightOperand} nicht
weiter berücksichtigt werden muss.
\begin{lstlisting}
	String name = (endLabel == null) ? code.nextLabel() : endLabel;
	if (leftOperand instanceof BinaryExpression)
		((BinaryExpression) leftOperand).generateCode(code, name);
	else
		leftOperand.generateCode(code);
	if (operator == Symbol.Id.ANDTHEN || operator == Symbol.Id.ORELSE)
	{
		code.println("MRM R5, (R2)");
		if (operator == Symbol.Id.ANDTHEN)
		{
			code.println("MRI R6, 1");
			code.println("SUB R6, R5");
			code.println("MRR R5, R6");
		}
		code.println("JPC R5, " + name);
	}
	
	if (rightOperand instanceof BinaryExpression)
		((BinaryExpression) rightOperand).generateCode(code, name);
	else
		rightOperand.generateCode(code);
\end{lstlisting}

\subsection{Auswertung von konstanten Ausdrücken (5\%)}

Um konstante Ausdrücke auszuwerten, haben wir ein Interface
(\texttt{IEvaluable}) erstellt, das alle Expressions implementiert, die
konstante Ausdrücke auswerten können (in unserem Fall sind das
\texttt{BinaryExpression} und \texttt{UnaryExpression}). Dort haben wir dann
gemäß den Hinweisen in der PDF die Auswertung konstanter Ausdrücke
vorgenommen.\par

Die Auswertung dieser Ausdrücke wird nach der Kontextanalyse angestoßen, damit
Typen bereits aufgelöst sind.


\subsection{Mehrere Fehlermeldungen (5\%)}

- nicht implementiert -

\subsection{Erweiterung um Zugriffsschutz (5\%)}

Analog zu vorhergegangenen Aufgaben muss die lexikalische Analyse um die
entsprechenden Schlüsselworte erweitert werden.\par

In der Syntax haben wir die Schlüsselworte \texttt{PUBLIC, PROTECTED} und
\texttt{PRIVATE} in \texttt{memberdecl} hinzugefügt. Sollte keines dieser
Schlüsselworte vor einer \texttt{meberdecl} geschrieben werden, wird
\texttt{PUBLIC} als Standard genommen.
\begin{lstlisting}
	AccessModificator mod = AccessModificator.PUBLIC;
	switch (symbol.id)
	{
		case PRIVATE:
			nextSymbol();
			mod = AccessModificator.PRIVATE;
			break;
		case PROTECTED:
			nextSymbol();
			mod = AccessModificator.PROTECTED;
			break;
		case PUBLIC:
			nextSymbol();
			mod = AccessModificator.PUBLIC;
			break;
	}
\end{lstlisting}

Um die Zugriffsklassen der Methoden und Variablen einer Klasse zu speichern,
haben wir folgende Attribute \texttt{ClassDeclaration} hinzugefügt.
\begin{lstlisting}
	HashMap<VarDeclaration, AccessModificator>		attributes		= new HashMap<VarDeclaration, ClassDeclaration.AccessModificator>();
	HashMap<MethodDeclaration, AccessModificator>	methods			= new HashMap<MethodDeclaration, ClassDeclaration.AccessModificator>();
\end{lstlisting}

Ob man nun Zugriff auf eine Variable oder Methode hat, wird in
\texttt{contextAnalysisForMember} in \texttt{VarOrCall} mit folgendem Code
geprüft:
\begin{lstlisting}
if (declarations.currentClass.attributes.containsKey(identifier.declaration))
switch (declarations.currentClass.attributes.get(identifier.declaration))
{
	case PRIVATE:
		if (!declarations.currentClass.equals(baseDeclarations.currentClass))
			throw new CompileException("...", position); 
		break; 
	case PROTECTED:
		if (!declarations.currentClass.isA(baseDeclarations.currentClass))
			throw new CompileException("...", position); 
		break;
}
\end{lstlisting}


\subsection{Erweiterung um Laufzeitfehler (5\%)}

Hier haben wir den Laufzeitfehler \texttt{DivisionByZero} hinzugefügt.\par
Dazu haben wir zunächst die Klasse \texttt{ExceptionClassDeclaration}
hinzugefügt. In dieser wird eine \textit{print}-Methode deklariert für den Fall,
dass eine \texttt{DivisionByZero}-Exception auftritt.
Für weitere Details siehe ExceptionClassDeclaration.java.

Bei der Synthese haben wir \texttt{BinaryExpression} um folgenden Code erweitert:
\begin{lstlisting}
	case DIV:
		String divLabel = code.nextLabel();
		code.println("JPC R5, " + divLabel);
		ExceptionClassDeclaration.divisionByZeroExceptionCall.generateCode(code);
		code.println("MRI R0, _end");
		code.println(divLabel + ":");
		code.println("DIV R6, R5");
		break;
\end{lstlisting}
Hier wird einfach geprüft, ob der Divisor 0 ist und wenn ja, wird der Text der
Exception ausgegeben.

\subsection{Typoperationen zur Laufzeit -- Typumwandlung (5\%)}

- nicht implementiert -

\subsection{Bessere Speicherbereinigung (5\%)}

- nicht implementiert -

\subsection{Keine automatische Initialisierung lokaler Variablen (5\%)}

- nicht implementiert -


%\section{Abbildungsverzeichnis}
%\listoffigures
\end{document}